From: Keir Fraser Date: Thu, 19 Mar 2009 10:09:24 +0000 (+0000) Subject: Fix a cpufreq userspace limitation bug X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13992^2~33 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:///%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:/?a=commitdiff_plain;h=7dc1bc818a6a4ba81ec923f0ec07a40199349eed;p=xen.git Fix a cpufreq userspace limitation bug Fix a cpufreq userspace limitation bug, so that userspace freq can return to correct freq when freq_limitation return to high value (like ppc event) Signed-off-by: Liu, Jinsong = --- diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index f2aaca7c24..bf476d584d 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -368,14 +368,7 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op) if ( !strnicmp(policy->governor->name, "userspace", CPUFREQ_NAME_LEN) ) - { - if ( freq < policy->min ) - freq = policy->min; - if ( freq > policy->max ) - freq = policy->max; - - ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); - } + ret = write_userspace_scaling_setspeed(op->cpuid, freq); else ret = -EINVAL; diff --git a/xen/drivers/cpufreq/cpufreq_misc_governors.c b/xen/drivers/cpufreq/cpufreq_misc_governors.c index a375a25bb9..1c63ec1815 100644 --- a/xen/drivers/cpufreq/cpufreq_misc_governors.c +++ b/xen/drivers/cpufreq/cpufreq_misc_governors.c @@ -18,34 +18,38 @@ #include #include -static unsigned int usr_speed; - /* * cpufreq userspace governor */ +static unsigned int cpu_set_freq[NR_CPUS]; + static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) { int ret = 0; - unsigned int freq; + unsigned int cpu; - if (!policy) + if (unlikely(!policy) || + unlikely(!cpu_online(cpu = policy->cpu))) return -EINVAL; switch (event) { case CPUFREQ_GOV_START: + if (!cpu_set_freq[cpu]) + cpu_set_freq[cpu] = policy->cur; + break; case CPUFREQ_GOV_STOP: + cpu_set_freq[cpu] = 0; break; case CPUFREQ_GOV_LIMITS: - freq = usr_speed ? : policy->cur; - if (policy->max < freq) + if (policy->max < cpu_set_freq[cpu]) ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - else if (policy->min > freq) + else if (policy->min > cpu_set_freq[cpu]) ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); - else if (usr_speed) - ret = __cpufreq_driver_target(policy, freq, + else + ret = __cpufreq_driver_target(policy, cpu_set_freq[cpu], CPUFREQ_RELATION_L); break; @@ -57,11 +61,34 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, return ret; } +int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq) +{ + struct cpufreq_policy *policy = cpufreq_cpu_policy[cpu]; + + if (!cpu_online(cpu) || !policy) + return -EINVAL; + + cpu_set_freq[cpu] = freq; + + if (freq < policy->min) + freq = policy->min; + if (freq > policy->max) + freq = policy->max; + + return __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); +} + static void __init cpufreq_userspace_handle_option(const char *name, const char *val) { - if (!strcmp(name, "speed") && val) - usr_speed = simple_strtoul(val, NULL, 0); + if (!strcmp(name, "speed") && val) { + unsigned int usr_cmdline_freq; + unsigned int cpu; + + usr_cmdline_freq = simple_strtoul(val, NULL, 0); + for (cpu = 0; cpu < NR_CPUS; cpu++) + cpu_set_freq[cpu] = usr_cmdline_freq; + } } struct cpufreq_governor cpufreq_gov_userspace = { diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 93acc7a4e0..bc525862bc 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -227,4 +227,6 @@ int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max, uint32_t *up_threshold); int write_ondemand_sampling_rate(unsigned int sampling_rate); int write_ondemand_up_threshold(unsigned int up_threshold); + +int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq); #endif /* __XEN_CPUFREQ_PM_H__ */